package org.springside.examples.showcase.utilities.wb;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springside.modules.utils.Encodes;

/**
 * A example that demonstrates how HttpClient APIs can be used to perform form-based logon.
 */
public class SinaLoginSha1JS {
	private static Logger log = Logger.getLogger(SinaLoginSha1JS.class);

	public static void main(String[] args) throws Exception {
		// d29yazQwNDF4JTQwc2luYS5jb20=
		System.out.println(getCookie("zhang_you_lei@163.com", "zhang_637"));
	}

	/**
	 * 得到登录新浪后的cookie
	 * 
	 * @return
	 */
	public static String getCookie(String uid, String pwd) {
		uid = Encodes.encodeBase64(uid.replaceAll("@", "%40").getBytes());
		String cookie = "";
		DefaultHttpClient httpclient = new DefaultHttpClient();
		try {
			HttpGet httpget = new HttpGet("http://login.sina.com.cn/sso/prelogin.php?entry=account&callback=sinaSSOController.preloginCallBack&su=ZGV2M3Rlc3QyJTQwMTYzLmNvbQ%3D%3D&client=ssologin.js(v1.3.17)");
			List<String> kv = doAction(httpclient, httpget);
			cookie = kv.get(0);
			String content = kv.get(1);
			String[] valuePair = StringUtils.substringBetween(content, "{", "}").replaceAll("\"", "").split(",");
			Map<String, String> valuePMap = new HashMap<String, String>();
			for (String str : valuePair) {
				String[] tem = str.split(":");
				valuePMap.put(tem[0], tem[1]);
			}
			Object o = exeJS(valuePMap, pwd);
			System.out.println(o.toString());
			String sp = o.toString();
			HttpPost httpost = new HttpPost("http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.3.17)");
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			nvps.add(new BasicNameValuePair("service", "sso"));
			nvps.add(new BasicNameValuePair("pwencode", "wsse"));
			nvps.add(new BasicNameValuePair("callback", "parent.sinaSSOController.loginCallBack"));
			nvps.add(new BasicNameValuePair("entry", "account"));
			nvps.add(new BasicNameValuePair("gateway", "1"));
			nvps.add(new BasicNameValuePair("nonce", valuePMap.get("nonce"))); // 用于生成密码
			nvps.add(new BasicNameValuePair("gateway", "1"));
			nvps.add(new BasicNameValuePair("returntype", "IFRAME"));
			nvps.add(new BasicNameValuePair("savestate", "0"));
			nvps.add(new BasicNameValuePair("encoding", "UTF-8"));
			nvps.add(new BasicNameValuePair("servertime", valuePMap.get("servertime"))); // 用于生成密码
			nvps.add(new BasicNameValuePair("setdomain", "1"));
			nvps.add(new BasicNameValuePair("useticket", "0"));
			nvps.add(new BasicNameValuePair("vsnf", "1"));
			nvps.add(new BasicNameValuePair("sp", sp)); // 密码
			nvps.add(new BasicNameValuePair("su", uid)); // 用户名

			httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
			httpost.addHeader("Accept", "application/x-shockwave-flash, image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword");
			httpost.addHeader("Accept-Language", "Accept-Language: zh-cn");
			httpost.addHeader("Connection", "Keep-Alive");
			httpost.addHeader("Content-Type", "application/x-www-form-urlencoded");
			httpost.addHeader("Host", "login.sina.com.cn");
			httpost.addHeader("Referer", "http://login.sina.com.cn/signup/signin.php");
			httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)");

			kv = doAction(httpclient, httpost);
			cookie = kv.get(0);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// When HttpClient instance is no longer needed, shut down the connection manager to ensure immediate deallocation of all system resources
			httpclient.getConnectionManager().shutdown();
		}
		return cookie;
	}

	/**
	 * 执行js文件
	 * 
	 * @param valuePMap
	 * @return
	 * @throws IOException
	 * @throws ScriptException
	 */
	private static Object exeJS(Map<String, String> valuePMap, String pwd) throws IOException, ScriptException {
		String jsfile = SinaLoginSha1JS.class.getClassLoader().getResource("jsfile.js").getFile();
		String jscontent = FileUtils.readFileToString(new File(jsfile), "utf-8");
		jscontent = jscontent.replaceAll("sinaweibopwd", pwd);
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("js");
		Object o = engine.eval(jscontent.replaceAll("\\$nonce\\$", valuePMap.get("nonce")).replaceAll("\\$servertime\\$", valuePMap.get("servertime")));
		return o;
	}

	/**
	 * 向服务器发请求
	 * 
	 * @param httpclient
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	private static List<String> doAction(DefaultHttpClient httpclient, HttpUriRequest request) throws IOException, ClientProtocolException {
		String cookie = "";
		String content = "";
		HttpResponse response = httpclient.execute(request);
		HttpEntity entity = response.getEntity();
		// Header[] h = response.getAllHeaders();
		// for (Header hdr : h) {
		// System.out.println(hdr.getName() + " " + hdr.getValue());
		// }
		System.out.println("Login form get: " + response.getStatusLine());
		EntityUtils.consume(entity);
		if (entity != null) {
			// System.out.println("Response content length: " + entity.getContentLength());
			InputStream in = entity.getContent();
			int len = new Long(entity.getContentLength()).intValue();
			byte[] buff = new byte[len];
			in.read(buff);
			content = new String(buff);
			System.out.println(content);
		}
		System.out.println("Post logon cookies:");
		List<Cookie> cookies = httpclient.getCookieStore().getCookies();
		if (cookies.isEmpty()) {
			System.out.println("None");
		} else {
			StringBuilder cookiesShow = new StringBuilder();
			for (int i = 0; i < cookies.size(); i++) {
				System.out.println("- " + cookies.get(i).toString());
				cookiesShow.append(cookies.get(i).getName());
				cookiesShow.append("=");
				cookiesShow.append(cookies.get(i).getValue());
				cookiesShow.append(";");
			}
			System.out.println(cookiesShow.toString());
			cookie = cookiesShow.toString();
		}

		List<String> result = new ArrayList<String>();
		result.add(cookie);
		result.add(content);
		return result;
	}
}
